from newspaper import Article
from datetime import datetime
import logging
import re
from bs4 import BeautifulSoup

class NewsParser:
    """通用新闻页面解析工具，主要依赖newspaper3k库，但增强了日期提取功能"""
    
    @classmethod
    def parse_news_page(cls, html, url, config=None):
        """
        解析新闻页面，主要使用newspaper3k，但增强了日期提取
        :param html: 页面HTML内容
        :param url: 新闻URL
        :param config: 自定义解析配置（仅用于兼容旧代码，实际未使用）
        :return: 解析结果字典
        """
        if not html:
            logging.warning(f"HTML内容为空，无法解析: {url}")
            return None
            
        logging.debug(f"开始使用newspaper3k解析页面: {url}")
        try:
            # 创建Article对象
            article = Article(url, language='zh')
            # 设置已下载的HTML
            article.download_state = 2
            article.html = html
            # 解析
            article.parse()
            
            # 获取标题、内容和发布时间
            title = article.title
            content = article.text
            publish_time = article.publish_date
            
            # 检查发布时间是否包含时和分，或者是否为空
            if not publish_time or (publish_time and (publish_time.hour == 0 and publish_time.minute == 0)):
                logging.debug(f"newspaper3k提取的时间不完整或为空: {publish_time}")
                # 尝试从HTML中提取更完整的时间信息
                extracted_time = cls.extract_date_from_html(html)
                if extracted_time:
                    publish_time = extracted_time
                    logging.info(f"成功从HTML中提取到完整的发布时间: {publish_time}")
            
            # 如果仍然没有提取到发布时间，使用当前时间
            if not publish_time:
                logging.warning(f"未能提取到发布时间，使用当前时间: {url}")
                publish_time = datetime.now()
            
            # 检查是否成功提取了标题和内容
            if not title or not content:
                logging.warning(f"newspaper3k解析不完整: 标题={bool(title)}, 内容={bool(content)}")
                return None
            
            return {
                'title': title,
                'content': content,
                'publish_time': publish_time
            }
            
        except Exception as e:
            logging.error(f"newspaper3k解析失败: {str(e)}")
            return None
    
    @staticmethod
    def extract_date_from_html(html):
        """
        从HTML中提取日期
        :param html: HTML内容
        :return: datetime对象或None
        """
        try:
            # 首先尝试提取带有时分的完整日期时间
            time_patterns = [
                r'日期[：:]\s*(\d{4})[-年/\.](\d{1,2})[-月/\.](\d{1,2})[日号]?\s*?(\d{1,2}):(\d{1,2})',
                r'时间[：:]\s*(\d{4})[-年/\.](\d{1,2})[-月/\.](\d{1,2})[日号]?\s*?(\d{1,2}):(\d{1,2})',
                r'发布[于]?[：:时间]?\s*(\d{4})[-年/\.](\d{1,2})[-月/\.](\d{1,2})[日号]?\s*?(\d{1,2}):(\d{1,2})',
                r'发表[于]?[：:时间]?\s*(\d{4})[-年/\.](\d{1,2})[-月/\.](\d{1,2})[日号]?\s*?(\d{1,2}):(\d{1,2})',
                r'(\d{4})[-年/\.](\d{1,2})[-月/\.](\d{1,2})[日号]?\s*?(\d{1,2}):(\d{1,2})'
            ]
            
            for pattern in time_patterns:
                match = re.search(pattern, html)
                if match:
                    try:
                        year, month, day, hour, minute = map(int, match.groups())
                        logging.debug(f"从HTML中提取到完整日期时间: {year}-{month}-{day} {hour}:{minute}")
                        return datetime(year, month, day, hour, minute)
                    except Exception as e:
                        logging.debug(f"提取完整日期时间失败: {str(e)}")
            
            # 如果没有找到带时分的日期，尝试提取仅有年月日的日期
            date_patterns = [
                r'日期[：:]\s*(\d{4})[-年/\.](\d{1,2})[-月/\.](\d{1,2})[日号]?',
                r'时间[：:]\s*(\d{4})[-年/\.](\d{1,2})[-月/\.](\d{1,2})[日号]?',
                r'发布[于]?[：:时间]?\s*(\d{4})[-年/\.](\d{1,2})[-月/\.](\d{1,2})[日号]?',
                r'发表[于]?[：:时间]?\s*(\d{4})[-年/\.](\d{1,2})[-月/\.](\d{1,2})[日号]?',
                r'日期：(\d{4})[-年/\.](\d{1,2})[-月/\.](\d{1,2})[日号]?',
                r'(\d{4})[-年/\.](\d{1,2})[-月/\.](\d{1,2})[日号]?',
                r'(\d{4})年(\d{1,2})月(\d{1,2})日',
                r'(\d{4})/(\d{1,2})/(\d{1,2})',
                r'(\d{4})-(\d{1,2})-(\d{1,2})'
            ]
            
            for pattern in date_patterns:
                match = re.search(pattern, html)
                if match:
                    # 提取年月日
                    if len(match.groups()) >= 3:
                        year = int(match.group(1))
                        month = int(match.group(2))
                        day = int(match.group(3))
                        
                        # 尝试在匹配到的日期附近查找时分信息
                        surrounding_text = html[max(0, html.find(match.group(0))-50):min(len(html), html.find(match.group(0))+100)]
                        time_match = re.search(r'(\d{1,2}):(\d{1,2})', surrounding_text)
                        
                        if time_match:
                            hour = int(time_match.group(1))
                            minute = int(time_match.group(2))
                            logging.debug(f"从HTML中提取到日期和附近的时间: {year}-{month}-{day} {hour}:{minute}")
                            return datetime(year, month, day, hour, minute)
                        else:
                            logging.debug(f"从HTML中仅提取到日期: {year}-{month}-{day}")
                            return datetime(year, month, day)
            
            # 使用BeautifulSoup尝试查找可能包含日期的元素
            soup = BeautifulSoup(html, 'html.parser')
            date_containers = soup.select('.date, .time, .publish-time, .article-date, .news-date')
            
            for container in date_containers:
                text = container.get_text()
                # 尝试提取完整日期时间
                for pattern in time_patterns:
                    match = re.search(pattern, text)
                    if match:
                        try:
                            year, month, day, hour, minute = map(int, match.groups())
                            logging.debug(f"从日期容器中提取到完整日期时间: {year}-{month}-{day} {hour}:{minute}")
                            return datetime(year, month, day, hour, minute)
                        except Exception:
                            pass
            
            logging.warning("未能从HTML中提取到日期")
            return None
        except Exception as e:
            logging.error(f"提取日期时出错: {str(e)}")
            return None